package com.himiotech.core.project.model.entity.gen;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.himiotech.core.framework.helper.constant.GenConstants;
import com.himiotech.core.project.model.base.BaseEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 业务表 gen_table
 *
 * @author ruoyi
 * @author wuwenbin
 */
@Data
@EqualsAndHashCode(callSuper = true)
@Accessors(chain = true)
public class GenTable extends BaseEntity {

    private static final long serialVersionUID = 1L;

    /**
     * 编号
     */
    @TableId(type = IdType.AUTO)
    private Long tableId;

    /**
     * 是否已经执行了菜单插入的 SQL 1已插入，0 未插入
     */
    private Integer sqlInsert;

    /**
     * 表名称
     */
    @NotBlank(message = "表名称不能为空")
    private String tableName;

    /**
     * 表描述
     */
    @NotBlank(message = "表描述不能为空")
    private String tableComment;

    /**
     * 关联父表的表名
     */
    private String subTableName;

    /**
     * 本表关联父表的外键名
     */
    private String subTableFkName;

    /**
     * 实体类名称(首字母大写)
     */
    @NotBlank(message = "实体类名称不能为空")
    private String className;

    /**
     * 使用的模板（crud单表操作 tree树表操作 sub主子表操作）
     */
    private String tplCategory;

    /**
     * 生成包路径
     */
    @NotBlank(message = "生成包路径不能为空")
    private String packageName;

    /**
     * 生成模块名
     */
    @NotBlank(message = "生成模块名不能为空")
    private String moduleName;

    /**
     * 生成业务名
     */
    private String businessName;

    /**
     * 生成功能名
     */
    @NotBlank(message = "生成功能名不能为空")
    private String functionName;

    /**
     * 生成作者
     */
    @NotBlank(message = "作者不能为空")
    private String functionAuthor;

    /**
     * 生成代码方式（0zip压缩包 1自定义路径）
     */
    private String genType;

    /**
     * 生成路径（不填默认项目路径）
     */
    private String genPath;

    /**
     * 主键信息
     */
    @TableField(exist = false)
    private GenTableColumn pkColumn;

    /**
     * 子表信息
     */
    @TableField(exist = false)
    private GenTable subTable;

    /**
     * 表列信息
     */
    @Valid
    @TableField(exist = false)
    private List<GenTableColumn> columns;

    /**
     * 其它生成选项
     */
    private String options;

    /**
     * 树编码字段
     */
    @TableField(exist = false)
    private String treeCode;

    /**
     * 树父编码字段
     */
    @TableField(exist = false)
    private String treeParentCode;

    /**
     * 树名称字段
     */
    @TableField(exist = false)
    private String treeName;

    /**
     * 上级菜单ID字段
     */
    @TableField(exist = false)
    private String parentMenuId;

    /**
     * 上级菜单名称字段
     */
    @TableField(exist = false)
    private String parentMenuName;

    /**
     * 表格默认排序字段名称
     */
    @TableField(exist = false)
    private String fieldName;

    /**
     * 表格默认排序字段方式
     */
    @TableField(exist = false)
    private String sortType;

    @TableField(exist = false)
    private String permissionPrefix;

    public static boolean isSub(String tplCategory) {
        return tplCategory != null && StrUtil.equals(GenConstants.TPL_SUB, tplCategory);
    }

    public static boolean isTree(String tplCategory) {
        return tplCategory != null && StrUtil.equals(GenConstants.TPL_TREE, tplCategory);
    }

    public static boolean isCrud(String tplCategory) {
        return tplCategory != null && StrUtil.equals(GenConstants.TPL_CRUD, tplCategory);
    }

    public static boolean isSuperColumn(String tplCategory, String javaField) {
        if (isTree(tplCategory)) {
            return StrUtil.equalsAnyIgnoreCase(javaField,
                    ArrayUtil.addAll(GenConstants.TREE_ENTITY, GenConstants.BASE_ENTITY));
        }
        return StrUtil.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY);
    }

    public boolean isSub() {
        return isSub(this.tplCategory);
    }

    public boolean isTree() {
        return isTree(this.tplCategory);
    }

    public boolean isCrud() {
        return isCrud(this.tplCategory);
    }

    public boolean isSuperColumn(String javaField) {
        return isSuperColumn(this.tplCategory, javaField);
    }

    public boolean hasUploadColumn() {
        return this.columns != null
                && this.columns.stream().anyMatch(col -> "upload".equals(col.getHtmlType()));
    }

    public List<GenTableColumn> uploadColumns() {
        return this.columns.stream().filter(col -> "upload".equals(col.getHtmlType())).collect(Collectors.toList());
    }

    public boolean hasTinyMceColumn() {
        return this.columns != null
                && this.columns.stream().anyMatch(col -> "tinymce".equals(col.getHtmlType()));
    }

    public List<GenTableColumn> tinyMceColumns() {
        return this.columns.stream().filter(col -> "tinymce".equals(col.getHtmlType())).collect(Collectors.toList());
    }

    public boolean hasDictColumn() {
        return this.columns != null
                && this.columns.stream().anyMatch(col -> StrUtil.isNotEmpty(col.getDictType()));
    }

    public List<GenTableColumn> dictColumns() {
        return this.columns.stream().filter(col -> StrUtil.isNotEmpty(col.getDictType())).collect(Collectors.toList());
    }

    public boolean hasBetweenSearchColumn() {
        return this.columns != null
                && this.columns.stream().anyMatch(col -> "BETWEEN".equals(col.getQueryType()));
    }

    public List<GenTableColumn> betweenSearchColumn() {
        return this.columns.stream().filter(col -> "BETWEEN".equals(col.getQueryType())).collect(Collectors.toList());
    }

    /**
     * 是否在添加、编辑中有日期组件
     *
     * @return
     */
    public boolean hasDateCpInDialog() {
        return columns != null
                && this.columns.stream().anyMatch(col -> ("Date".equals(col.getJavaType()) || "LocalDateTime".equals(col.getJavaType())) && (col.isEdit() || col.isInsert()));
    }

    public List<GenTableColumn> listColumns() {
        return columns.stream().filter(GenTableColumn::isList).collect(Collectors.toList());
    }

    /**
     * 除了主键之外，是否编辑的字段和添加的字段是否全部相同
     *
     * @return
     */
    public boolean isAddColCntEqEditColCntExcludePk() {
        return this.columns != null
                && columns.stream().allMatch(genTableColumn -> {
                    boolean isPk = genTableColumn.isPk();
                    boolean insert = genTableColumn.isInsert();
                    boolean edit = genTableColumn.isEdit();
                    return isPk || insert == edit;
                });
    }

}